from market.models import Strategy, Asset, Player, Fund, WebSiteComment, BetRoom
from market.models import History, AssetForHistory, StrategyForHistory, PlayerPortfolioForHistory
from market.strategyAndFundHelper import getPortfolioMtM, isStrategyValid, getFundMtM, getPercOnAssetInStrat
from market.marketData import MarketData
from market.playerData import PlayerData
from django.contrib.auth.models import User
from django.utils import simplejson
from market.strategyAndFundHelper import getFundMtM, getPortfolioMtM
import os, os.path, shutil
from subprocess import call
from subprocess import Popen, PIPE
from django.test.client import Client
import getpass
import sys, filecmp

##############################################################################################################################
# destroy the data base and create a new empty one.
def initContractBetrooms():

    # get the current data base file and suppress it
    dbfiles = [os.path.join(root, name)
                    for root, dirs, files in os.walk(os.getcwd())
                        for name in files if name.endswith(('.db', '.db'))]
    
    if len(dbfiles)>1:
            raise Exception('too many data base. Please clean folder before testting')
        
    if len(dbfiles)==0:
        # create the data base with superuser Jean
        print 'You will be asked for a password twice to create the test data base and once to use it.'
        print 'Input any easy to type value'
        print 'If running the debug server after the tests, you will be able to browse the website with the user name Jean and the input password.'
        p = Popen(['python', 'manage.py', 'syncdb'], shell=True, stdin=PIPE, stdout=PIPE )#
        # answer the question ask by syncdb
        p.communicate('yes\nJean\nj@g.com\n')#It is not working for the passwords, we have to manually input it
    if len(dbfiles)==1:
        try:
            u = User.objects.get( is_superuser = True )
            if u.username != 'Jean':
                raise 'dummy'
        except:
            raise Exception('If there is not just one super user called Jean, you will need to manually suppress the data base file before running the tests') 
        print 'The data base will be cleaned up. Only the super user and the password will remain.'
        continueAsking = True
        while continueAsking:
            answer = raw_input('Do you want to continue? Please enter yes/exit: ')
            if answer == 'exit':
                raise Exception('test interupted by the user')
            if answer != 'yes':
                print 'Enter ONLY yes OR exit (check case)'
            else:
                continueAsking = False
        print 'Cleaning the data base...'
        
        for b in BetRoom.objects.all():
            b.delete()
        for u in User.objects.filter( is_superuser = False ):
            u.delete()


##############################################################################################################################
# test that the urls are avaialble
def testURLS(password):
        
    myURLsGet = [   'betrooms', '', 'celibax', 'market', 'strategies', 'help', 'rules', 'logoutView', 'celibax',
                    'createBetroom/step1', 'createBetroom/step2', 'createBetroom/step3', 'createBetroom/step4', 'createBetroom/step5',
                    'enterBetroom/step1', 'enterBetroom/step2', 
                    'json/getAllJsons', 'json/getSpecificJson', 'comet/getMarketUpToDateStatus', 'comet/getChatUpToDateStatus',
                    'admin2', 'admin2/saveAndCreateAdmin', 'admin2/deleteAssetAdmin', 'admin2/addPlayerAdmin']

    c = Client()
    for url in myURLsGet:
        response = c.get('/'+url+'/', {'username': 'Jean', 'password': password})
        if int(response.status_code)!= 302 and int(response.status_code)!= 200:
            raise Exception(' get url '+ url + ' failed with status ' + str(response.status_code) )
        
    myURLsPost = [ 'sellAsset',  'SubmitNewRepartition',  'SubmitNewStrategyMtmRep',  'killAssetInGloryMode',  'addSelectedStratInTable',
                   'removeUninvestedStratFromTable',  'postComment',  'hideComment',  'enterBetroom', 'admin2/saveRoom',
                   'admin2/createNewPlayer', 'admin2/killAssetMtM', 'admin2/killAssetNumbers', 'admin2/suspend', 'admin2/resume',
                   'createBetroom/create', 'createBetroom/newAsset', 'createBetroom/changeNewAsset', 'createBetroom/deleteNewAsset',
                   'createBetroom/validateAssets', 'createBetroom/adminOrPlayer', 'createBetroom/setViewAdmin', 'createBetroom/deleteBetroom',
                   'createBetroom/launchBetroom', 'createBetroom/launchBetroom', 'enterBetroom/createPlayer', 'enterBetroom/setViewPlayer']

    
    for url in myURLsPost:
        response = c.post('/'+url+'/', {'username': 'Jean', 'password': password})
        if int(response.status_code)!= 302 and int(response.status_code)!= 200 :
            raise Exception(' post url '+ url + ' failed with status ' + str(response.status_code) )    
    

##############################################################################################################################
# create the new betroom for all the repositories in savedRoomFiles beginning by 'test_'
def initBetrooms(password):
    # get the current data base file and suppress it
    path = os.path.join( os.getcwd(), 'market', 'tests', 'savedRoomFiles' )
    testDirsAndbetroomNames = [(os.path.join(path, name),name)
             for root, dirs, files in os.walk(path)
             for name in dirs
             if name.startswith(('betroom'))]

    user = User.objects.get(username = 'Jean')
    
    for dirAndName in testDirsAndbetroomNames:
        #c = Client(enforce_csrf_checks=True)
        b = BetRoom(
            personInCharge = user, # account holder in charge of the administration of the bet room 
            name =dirAndName[1],
            description = ''#description of what is traded is in this bet room
          )
        b.save()
        c = Client()
        response = c.post('/login/', {'username': 'Jean', 'password': password})
        response = c.post('/admin2/createRoom/', {'betroom':dirAndName[1], 'path':path })

    return testDirsAndbetroomNames

##############################################################################################################################   
# save the betroom linked to testDirsAndNames and compare the files in /savedRoomFiles/ with the files in pathContainingReferenceFiles
def saveBetroomsAndCompare( password, testDirsAndbetroomNames, pathContainingReferenceFiles ):
    
    for dirAndName in testDirsAndbetroomNames:
        b = BetRoom.objects.get( name = dirAndName[1] )
        b.save()
        c = Client()
        response = c.post('/login/', {'username': 'Jean', 'password': password})
        response = c.post('/admin2/saveRoom/', {'betroom':dirAndName[1]})
        # compare the generated folder anb the folder saved in the test repository for the comparison
        comparison = filecmp.dircmp(
            os.path.join( os.getcwd(), 'savedRoomFiles', dirAndName[1] ),#where the files have just been saved
            os.path.join( pathContainingReferenceFiles, dirAndName[1] )#where the reference files lie
            )
        if len( comparison.common_funny ) > 0:
            raise Exception('In ' + dirAndName[1] + ' the following files are funny ' + str(  comparison.common_funny ) )
        if len( comparison.diff_files ) > 0:
            raise Exception('In ' + dirAndName[1] + ' the following files differ ' + str(  comparison.diff_files ) )
        print '- Files generated for ' + dirAndName[1] + ' have been success fully comparated to those in ' + dirAndName[0]
        

##############################################################################################################################
# For all the betroom, this perform the following test:
# - register every player view and mtm
# - change the view of all pplayer to 100 percent on the first asset.
# - check that the market is 100% too
# - set bacj the player view in the reverse order
# - check that the market view and the player MtMs are the initial ones
def marketAt100AndComeBackToInitialPoint():

    for betroom in BetRoom.objects.all():
        print 'TEST BETROOM: ' +  betroom.name
        # get assets and players
        assets = Asset.objects.filter( betroom=betroom, isAvailableForStandardStrategy = True )
        players = Player.objects.filter(mainStrategy__betroom=betroom)
        # get the main std asset on which every body invest
        stdAssets = Asset.objects.filter( betroom=betroom, isStandard = True, isAvailableForStandardStrategy = True )
        if len(stdAssets)==0:
            raise Exception("There is no standard asset in " + betroom.name)
        mainAsset = stdAssets[0]
        mktOld = MarketData(betroom)
        # save down the view and mtm of every player
        playerViewAndMtM = [(p, getPortfolioMtM( p, mktOld ), [ (a, getPercOnAssetInStrat( p.mainStrategy, a)) for a in assets]) for p in players]
        # set the new repartition (everything on the main asset) for all the players
        repartition = [ (a,float(a==mainAsset)) for a in assets ]
        for p in players:
            pd = PlayerData( p.userBeingThisPlayer, p.mainStrategy.betroom )
            print p.userBeingThisPlayer.username + ' sets 100 percent on ' + mainAsset.name + ' in betroom: ' + betroom.name +'...'
            pd.setNewView( repartition )
        # check that the new market is valid
        mktNew = MarketData(betroom)
        for a in stdAssets:
            expectation = mktNew.getMarketExpectation( a )
            if a==mainAsset and  expectation!= 1:
                raise Exception( betroom.name +' :'+a.name+' is the main asset but has an expectation of ' + str(expectation) )
            if a!=mainAsset and  expectation!= 0:
                raise Exception( betroom.name +' :'+a.name+' is the not the main asset but has an expectation of ' + str(expectation) )
        #set back the player views in the reverse order
        for pIndex in range(len(players)):
            pIndex2 = len(players)-1-pIndex
            p = players[pIndex2]
            print p.userBeingThisPlayer.username + ' sets back his strategy in betroom: ' + betroom.name +'...'
            pd = PlayerData( p.userBeingThisPlayer, p.mainStrategy.betroom )
            pd.setNewView( playerViewAndMtM[pIndex2][2] )
        # check that the new mtms are also the old ones
        mktNew = MarketData(betroom)
        stop = False
        for pIndex in range(len(players)):
            p = players[pIndex]
            newMtM = getPortfolioMtM( p, mktNew )
            if abs(newMtM-playerViewAndMtM[pIndex][1] ) > 0.000000001:
                stop = True
                print 'MtM of ' + p.userBeingThisPlayer.username+' has change from '+ str(playerViewAndMtM[pIndex][1])+ ' to '+ str(newMtM)
        if stop:
            raise Exception( 'test stoped because of previous errors' )
        print '\n'
        


























    
    
